#include <iostream>
#include <cstdio>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <cstring>

const int PORT = 8080;

int main()
{
    int server_fd;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);

    // 1. 创建套接字
    // Create socket file descriptor
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("Socket failed");
        return -1;
    }

    // 1.1 设置套接字选项 -- 避免地址已被使用
    // Attach socket to the port
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
    {
        perror("Setsockopt failed");
        return -1;
    }

    // 2. 填充数据
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // 3. 绑定 Bind the socket to the network address and port
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0){
        perror("Bind failed");
        return -1;
    }

    // 4. 监听  Start listening for incoming connections
    if (listen(server_fd, 3) < 0){
        perror("Listen failed");
        return -1;
    }

    std::cout << "Server is listening on port " << PORT << std::endl;
    
    int new_socket;
    while (1)
    {
        // 5. 接受连接 Accept an incoming connection
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0){
            perror("Accept failed");
            return -1;
        }

        // 6. 接收请求
        char buffer[1024] = {0}; // 定义接收缓冲区
        int ret = recv(new_socket, buffer, sizeof(buffer), 0);
        if (ret < 0){
            perror("Receive failed");
            close(new_socket);
            continue;
        }
        std::cout << "Message received from client: " << buffer << std::endl;

        // 7. 发送响应
        std::string body = "<html><body>Hello Island</body></html>";
        std::string header = "HTTP/1.1 200 OK\r\n"
                             "Content-Type: text/html\r\n"
                             "Content-Length: " + std::to_string(body.size()) + "\r\n"
                             "Connection: close\r\n\r\n";
        std::string response = header + body;
        ret = send(new_socket, response.c_str(), response.size(), 0);
        if(ret < 0){
            perror("Send failed");
            close(new_socket);
            continue;
        }
        close(new_socket);
    }
    close(server_fd);
    return 0;
}